/**
 *
 * @file options.c
 *
 * @brief Command line parser
 *
 * $Id: options.c 116 2009-01-15 07:23:52Z henri.doreau $
 */

/*
 * This file is part of Tsar.
 *
 * Tsar is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Tsar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Tsar.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <options.h>
#include <tsar.h>




int tsar_get_options( int argc, char **argv, opt_t * o )
{
    int opt, index;
    bool_t forceTraceOpt = false;  /* Print out a summarry of options states and values before returning */
    unsigned long tmpUnsignedLong; /* Used in conversion from string to unsigned long to a shorter type */
    struct option longopt[] = {
        /* --- Long format only options --- */
        { "debug",      no_argument,        NULL, '0' },
        { "promisc",    no_argument,        NULL, '0' },
        { "trace-opt",  no_argument,        NULL, '0' },
        /* --- Both long and short format options --- */
        /* -- Arguments options -- */
        { "interface",  required_argument,  NULL, 'I' },
        { "output",     required_argument,  NULL, 'o' },
        { "timeout",    required_argument,  NULL, 't' },
        { "http-port",  required_argument,  NULL, 'p' },
        { "load-file",  required_argument,  NULL, 'L' },
        { "filter",     required_argument,  NULL, 'f' },
        /* -- No argument options -- */
        { "version",    no_argument,        NULL, 'V' },
        { "help",       no_argument,        NULL, 'h' },
        { 0, 0, 0, 0 }
    };

    if ( argc == 1 )
        fprintf( stderr, "Warning : You launched %s without arguments.\n"
                "Software is running with default settings but it is probably not what you want.\n"
                "You can get a brief command line syntax memo typing %s --help\n\n", 
                argv[0], argv[0] );

    /* --- Set options to their default values --- */
    SET_OPTIONS_DEFAULT( o );
    /* --- *********************************** --- */
    /* --- Command line parsing loop --- */
    while ( ( opt = getopt_long( argc, argv, "0I:o:t:p:L:f:vVh", longopt, &index ) ) != -1 )
    {
        switch( opt )
        {
            case    '0' :
                if ( strcmp( longopt[index].name, "debug" ) == 0 )
                    o->debug = true;
                else if ( strcmp( longopt[index].name, "promisc" ) == 0 )
                    o->promisc = !DEFAULT_PROMISC_MODE_ENABLED;
                else if ( strcmp( longopt[index].name, "trace-opt" ) == 0 )
                    forceTraceOpt = true;
                else
                    /* Should never be reached */
                    fatal( "WTF are we doing there?!\n" );
                    break;

            /* Network interface */
            case    'I' :
                o->iface = optarg;
                break;

            /* Output file name */
            case    'o' :
                o->outputFile = optarg;
                assert( o->outputFile[0] != '\0' );  /* No NULL filename please... */
                break;

            /* Refresh period */
            case    't' :
                if ( str2ulong( optarg, &(o->timeoutMs) ) )
                {
                    /* This does not look like a number of seconds!! */
                   fatal( "Invalid number of milliseconds supplied for timeout : %s\n", optarg );
                }
                assert( o->timeoutMs > 0 );
                break;

            case    'p' :
                if (  str2ulong( optarg, &tmpUnsignedLong ) )
                {
                    fatal( "Invalid port number supplied : %s. Must be an integer contained between 0 and 65535\n", optarg );
                }
                else if ( tmpUnsignedLong > 65535 )
                {
                    fatal( "Invalid port number supplied : %s. Must be contained between 0 and 65535\n", optarg );                         
                }
                else
                {
                    o->httpServerPort = tmpUnsignedLong;    
                }
                break;

            /* Don't launch sniffer, load specified pcap file instead */
            case    'L' :
                o->startSniffer = false;
                o->pcapFile     = optarg;
                break;

            case    'f' :
                o->snifferFilter = optarg;
                break;

            /* Verbosity level (the less is the most verbose...) */
            case    'v' :
                if ( o->verbosityLevel < MAX_VERBOSITY_LEVEL )
                    o->verbosityLevel++;
                break;

            /* Print out version and exit */
            case    'V' :
                fprintf( stdout, "%s %s ( %s )\n", _NAME_,  _VERSION_, _URL_ );
                exit( EXIT_FAILURE );

            /* Help message */
            case    'h' :
            default     :
                return -1;
        }
    }

    /*
     * FIXME : should be placed at the same level than end_output()  
     * Start verbosity levels controlled
     * output manager
     */
    init_output( o );
    /* If verbosity level is high enough or 
     * if explicitly specified va --trace_opt option  : 
     * print out enabled options 
     */
    trace_options( o, forceTraceOpt );

    /* If we are here, then things passed well... */
    return 0;
}

void trace_options( opt_t * o, bool_t forceTraceOpt )
{
    int priority = MESSAGE_INFO;
        
    /* Hisghest verbosity level : force printing if explicitly required */
    if ( forceTraceOpt )
        priority = MESSAGE_ALERT;

    print( priority, "\n-- Options trace --\n" );
    print( priority, "Network interface  : %s\n", o->iface );
    print( priority, "Output filename    : %s\n", o->outputFile );
    print( priority, "Refresh dump file  : %lu (ms)\n", o->timeoutMs );
    print( priority, "Http server's port : %hu\n", o->httpServerPort );
    print( priority, "Start sniffer      : %s (to file : %s)\n", BOOL_STATE( o->startSniffer ), o->pcapFile );
    print( priority, "Apply filter       : %s\n", o->snifferFilter );
    print( priority, "Verbosity level    : %u\n", (int)o->verbosityLevel );
    print( priority, "Debug flag         : %s\n", BOOL_STATE( o->debug ) );
    print( priority, "Promiscuous mode   : %s\n", BOOL_STATE( o->promisc ) );
    print( priority, "Trace options      : %s\n", BOOL_STATE( forceTraceOpt ) );
    print( priority, "-- ------- ----- --\n" );
}

